import {iv as ivCfg, key as keyCfg, footer, baseUrl} from '@/js/common/config'
import lockScreenBg from "/public/images/lock-screen-bg.jpg"

layui.define(['jquery', 'form'], e => {
    const $ = layui.jquery, form = layui.form, base64 = window.CryptoJS.enc.Base64,
        aes = window.CryptoJS.AES,
        iv = base64.parse(ivCfg),
        key = base64.parse(keyCfg)

    /*字符串加解密（用于前后端数据加密传输）*/
    const encrypt = plaintext => aes.encrypt(plaintext, key, {iv: iv}).toString(),
        decrypt = ciphertext => aes.decrypt({ciphertext: base64.parse(ciphertext)}, key, {iv: iv}).toString(window.CryptoJS.enc.Utf8)

    /*base64 编码、解码*/
    const base64Decode = str => base64.parse(str),
        base64Encode = str => base64.stringify(window.CryptoJS.enc.Utf8.parse(str))

    /*获取、移除 token*/
    const setToken = token => sessionStorage.setItem('token', token),
        getToken = () => sessionStorage.getItem('token'), isLogin = () => {
            if (null == getToken())
                window.location.href = '/login.html'
        }, removeToken = () => sessionStorage.removeItem('token')

    const hideMenu = () => {
        $('.layui-layout-admin > .layui-side').css('display', 'none')
        $('.layui-layout-admin > .layui-header').css('left', '0')
        $('.layui-layout-admin > .layui-body').css('left', '0')
        $('.layui-layout-admin > .layui-footer').css('left', '0')
    }, showMenu = () => {
        $('.layui-layout-admin > .layui-side').css('display', 'block')
        $('.layui-layout-admin > .layui-header').css('left', '150px')
        $('.layui-layout-admin > .layui-body').css('left', '150px')
        $('.layui-layout-admin > .layui-footer').css('left', '150px')
    }

    const lockScreen = () => {
        layer.open({
            type: 1,
            title: false, // 禁用标题栏
            closeBtn: false, // 禁用默认关闭按钮
            area: ['100%', '100%'],
            scrollbar: false, // 暂时屏蔽浏览器滚动条
            anim: -1, // 禁用弹出动画
            isOutAnim: false, // 禁用关闭动画
            resize: false,  // 禁用右下角拉伸尺寸
            id: 'ID-layer-demo-inst',
            skin: 'class-demo-layer-lockscreen',
            content: ['<div class="layui-form">',
                '<div class="layui-input-wrap">',
                '<input type="password" class="class-demo-layer-pin" lay-affix="eye">',
                '<div class="layui-input-suffix">',
                '<i class="layui-icon layui-icon-right" id="unlock-screen"></i>',
                '</div>',
                '</div>',
                '<div>输入 锁屏密码 后回车，即可退出锁屏</div>',
                '</div>'].join(''),
            success: (layero, index) => {
                sessionStorage.setItem('isLockScreen', encrypt('lock'))
                $('.class-demo-layer-lockscreen').css({backgroundImage: 'url(' + lockScreenBg + ')'})
                let input = layero.find('input')

                form.render()
                input.focus()
                let unlockScreen = layero.find('#unlock-screen');
                unlockScreen.on('click', () => {
                    if ($.trim(input[0].value) === getUser()?.screen) {
                        sessionStorage.removeItem('isLockScreen')
                        layer.close(index)
                        layer.closeLast('dialog')
                    } else {
                        layer.msg('锁屏密码输入有误', {offset: '16px', anim: 'slideDown'})
                        input.focus()
                    }
                })
                input.on('keyup', e => {
                    let keyCode = e.keyCode;
                    if (keyCode === 13)
                        unlockScreen.trigger('click');
                });
            }
        })
    }

    let lock = sessionStorage.getItem('isLockScreen')
    if (lock && decrypt(lock) === 'lock')
        lockScreen()
    const reqData = d => {
            if (d) {
                let s = decrypt(d)
                try {
                    return JSON.parse(s);
                } catch (e) {
                    return s
                }
            }
            return undefined
        }, reqO = (url, data, callback, type, header, upload) => {
            if (!['sys/user/login', 'sys/user/logout'].includes(url))
                isLogin()

            let i = layer.load(0, {shade: true})
            $.ajax({
                url: baseUrl + url,
                type: type,
                data: data ? (upload ? data : encrypt(JSON.stringify(data))) : undefined,
                headers: header ?? {
                    Authorization: getToken()
                },
                contentType: upload ? false : "application/json; charset=utf-8",
                processData: !(upload && upload === true),
                dataType: "json"
            }).done(d => {
                layer.close(i)
                if (d.code === -200) {
                    layer.msg(d.msg)
                    window.location.href = '/login.html'
                } else
                    callback({
                        code: d.code,
                        msg: d.msg,
                        data: upload ? reqData(d.data) : d.data
                    })
            }).fail((jqXHR, textStatus, errorThrown) => {
                layer.close(i)
                console.error("请求失败:", textStatus, ", 错误信息:", errorThrown)
            })
        }, req = (url, data, callback, type, header) => reqO(url, data, d => callback({
            code: d.code,
            msg: d.msg,
            data: reqData(d.data)
        }), type, header),
        reqM = (url, data, callback, type, header) => req(url, data, d => {
            layer.msg(d.msg)
            if (d.code === 200 && callback)
                setTimeout(() => callback(d), 1000)
        }, type, header),
        upload = (url, data, callback, header) => reqO(url, data, d => callback(d), 'POST', header, true),
        postO = (url, data, callback, header) => reqO(url, data, d => callback(d), 'POST', header),
        post = (url, data, callback, header) => req(url, data, d => callback(d), 'POST', header),
        postM = (url, data, callback, header) => reqM(url, data, d => callback ? callback(d) : undefined, 'POST', header),
        getO = (url, data, callback, header) => reqO(url, data, d => callback(d), 'GET', header),
        get = (url, data, callback, header) => req(url, data, d => callback(d), 'GET', header),
        getM = (url, data, callback, header) => reqM(url, data, d => callback(d), 'GET', header)

    const setFooter = show => {
        if (show) {
            $('.layui-layout-admin').append('<div class="layui-footer">' + footer + '</div>')
            $('.layui-layout-admin .layui-body').css('padding-bottom', '34px')
        } else {
            $('.layui-footer').remove()
            $('.layui-layout-admin .layui-body').css('padding-bottom', '0')
        }
    }

    const setUser = user => sessionStorage.setItem('user', encrypt(JSON.stringify(user))),
        getUser = () => JSON.parse(decrypt(sessionStorage.getItem('user')))

    const enumObj = tableFieldCamel => new Promise(resolve => post('sys/comm/enumo/' + tableFieldCamel, undefined, ({data}) => resolve(data))),
        enumList = tableFieldCamel => new Promise(resolve => post('sys/comm/enuma/' + tableFieldCamel, undefined, ({data}) => resolve(data)))

    const dictObj = dictGroupCode => new Promise(resolve => post('sys/dict_group/itemo/' + dictGroupCode, undefined, ({data}) => resolve(data))),
        dictList = dictGroupCode => new Promise(resolve => post('sys/dict_group/itema/' + dictGroupCode, undefined, ({data}) => resolve(data)))

    const confirm = (message, callback, title) => layer.confirm(message, {
        btn: ['确定', '取消'],
        skin: 'layui-layer-molv',
        title: title,
        icon: 3
    }, () => callback())

    /**
     * 根据枚举类型，渲染单选框
     *
     * @param clazz 单选框上级div的class属性（作为渲染后radio的name属性）
     * @param tableFieldCamel 枚举类型（表字段驼峰命名）
     * @param checkedKey 默认选中的key
     * @param required 是否必填
     */
    const enumRadio = (clazz, tableFieldCamel, checkedKey, required) => enumList(tableFieldCamel).then(list => {
        $('.' + clazz).html(list.reduce((p, c) => {
            p += '<input type="radio" name="' + clazz + '" value="' + c.key + '" title="' + c.value + '" ' + (c.key === checkedKey ? 'checked' : '') + ' lay-filter="' + clazz + '-filter" ' + (required ? ' lay-verify="required"' : '') + '/>'
            return p
        }, ''))
        form.render('radio')
    })

    /**
     * 根据枚举类型，渲染单选框
     *
     * @param clazz 单选框上级div的class属性（作为渲染后radio的name属性）
     * @param json 对象key作为value，对象value作为title
     * @param checkedKey 默认选中的key
     * @param required 是否必填
     */
    const jsonRadio = (clazz, json, checkedKey, required) => {
        $('.' + clazz).html(Object.entries(json).reduce((p, c) => {
            p += '<input type="radio" name="' + clazz + '" value="' + c[0] + '" title="' + c[1] + '" ' + (c[0] === checkedKey ? 'checked' : '') + ' lay-filter="' + clazz + '-filter" ' + (required ? ' lay-verify="required"' : '') + '/>'
            return p
        }, ''))
        form.render('radio')
    }

    /**
     * 根据数组类型，渲染下拉框
     *
     * @param clazz 下拉框上级div的class属性（作为渲染后select的name属性）
     * @param arr 数组
     * @param checkedKey 默认选中的key
     * @param required 是否必填
     * @param tip 下拉框提示
     */
    const arrSelect = (clazz, arr, checkedKey, required, tip) => {
        $('.' + clazz).html(arr.reduce((p, c) => {
            p += '<option value="' + c.key + '" ' + (checkedKey && checkedKey === c.key ? 'selected' : '') + '>' + c.value + '</option>'
            return p
        }, '<select name="' + clazz + '" lay-filter="' + clazz + '-filter" lay-search ' + (required ? ' lay-verify="required"' : '') + '><option value="">' + (tip ?? '请选择') + '</option>') + '</select>')
        form.render('select')
    }

    /**
     * 设置权限
     *
     * @param permArr 权限数组
     */
    const setPerm = permArr => sessionStorage.setItem('perm', encrypt(JSON.stringify(permArr)))
    /**
     * 权限按钮过滤（无权限的按钮会被移除，仅保留有权限的按钮）
     * 生产环境使用，开发环境使用会报错（关闭报错后可以继续使用）
     *
     * @param devEnvShow 开发环境是否调用（布尔型）
     */
    const perm = devEnvShow => {
        if (devEnvShow || process.env.NODE_ENV === 'production') {
            let permArr = [], perm = sessionStorage.getItem('perm')
            if (perm)
                permArr = decrypt(perm)
            $('[perm]').each((i, o) => {
                if (!permArr.includes($(o).attr('perm')))
                    $(o).remove()
            })
        }
    }

    e('admin', {
        encrypt,
        decrypt,
        setToken,
        getToken,
        removeToken,
        hideMenu,
        showMenu,
        lockScreen,
        isLogin,
        base64Encode,
        base64Decode,
        req,
        post,
        postM,
        postO,
        upload,
        get,
        getM,
        getO,
        setFooter,
        setUser,
        getUser,
        enumObj,
        enumList,
        arrSelect,
        dictObj,
        dictList,
        confirm,
        enumRadio,
        jsonRadio,
        setPerm,
        perm
    })
});